package services

import (
    "context"
    "encoding/json"
    "time"
    "github.com/beego/beego/v2/core/logs"
    "github.com/beego/beego/v2/server/web"
    "go.etcd.io/etcd/client/v3"
    "volux/models"
    "volux/utils"
)

type HeartbeatService struct {
    nodeID       string
    nodeName     string
    interval     time.Duration
    etcdClient   *utils.EtcdClient
    stopChan     chan struct{}
    gatewayStats *models.GatewayStatus
}

func NewHeartbeatService(nodeID, nodeName string, interval int) (*HeartbeatService, error) {
    etcdClient, err := utils.NewEtcdClient(
        web.AppConfig.DefaultStrings("etcd::endpoints", []string{"localhost:2379"}),
        web.AppConfig.DefaultString("etcd::username", ""),
        web.AppConfig.DefaultString("etcd::password", ""),
    )
    if err != nil {
        return nil, err
    }

    return &HeartbeatService{
        nodeID:     nodeID,
        nodeName:   nodeName,
        interval:   time.Duration(interval) * time.Second,
        etcdClient: etcdClient,
        stopChan:   make(chan struct{}),
        gatewayStats: &models.GatewayStatus{
            StartTime: time.Now(),
        },
    }, nil
}

func (hs *HeartbeatService) Start() {
    go hs.heartbeatLoop()
}

func (hs *HeartbeatService) Stop() {
    close(hs.stopChan)
}

func (hs *HeartbeatService) heartbeatLoop() {
    ticker := time.NewTicker(hs.interval)
    defer ticker.Stop()

    for {
        select {
        case <-ticker.C:
            if err := hs.sendHeartbeat(); err != nil {
                logs.Error("Failed to send heartbeat: %v", err)
            }
        case <-hs.stopChan:
            return
        }
    }
}

func (hs *HeartbeatService) sendHeartbeat() error {
    // 更新网关状态
    hs.updateGatewayStats()

    // 准备心跳数据
    heartbeat := models.GatewayNode{
        ID:            hs.nodeID,
        Name:          hs.nodeName,
        Status:        "running",
        LastHeartbeat: time.Now(),
        Version:       "1.0.0",
        Stats:         hs.gatewayStats,
    }

    // 序列化心跳数据
    data, err := json.Marshal(heartbeat)
    if err != nil {
        return err
    }

    // 写入etcd，设置TTL为心跳间隔的2倍
    ctx := context.Background()
    leaseResp, err := hs.etcdClient.Client.Grant(ctx, int64(hs.interval.Seconds()*2))
    if err != nil {
        return err
    }

    // 使用租约写入心跳数据
    _, err = hs.etcdClient.Client.Put(ctx, "/gateways/"+hs.nodeID, string(data), clientv3.WithLease(leaseResp.ID))
    return err
}

func (hs *HeartbeatService) updateGatewayStats() {
    spdkClient := utils.GetSPDKClient()
    if spdkClient == nil {
        return
    }

    // 获取子系统数量
    if resp, err := spdkClient.Call("nvmf_get_subsystems", nil); err == nil {
        if subsystems, ok := resp.Result.([]interface{}); ok {
            hs.gatewayStats.SubsystemCount = len(subsystems)
        }
    }

    // 获取bdev数量
    if resp, err := spdkClient.Call("bdev_get_bdevs", nil); err == nil {
        if bdevs, ok := resp.Result.([]interface{}); ok {
            hs.gatewayStats.BdevCount = len(bdevs)
        }
    }

    // TODO: 添加CPU和内存使用率统计
}
